/*********************************************************************************
 *      Copyright:  (C) 2025 iot25<lingyun@email.com>
 *                  All rights reserved.
 *
 *       Filename:  proc.c
 *    Description:  This file 
 *                 
 *        Version:  1.0.0(02/05/25)
 *         Author:  iot25 <lingyun@email.com>
 *      ChangeLog:  1, Release initial version on "02/05/25 16:42:31"
 *                 
 ********************************************************************************/
#include "proc.h"

int proc_deamon(int daemon_flag, char *pidfile)
{
	if ( !pidfile )
	{
		return 0;
	}

	if ( !proc_check_daemon(pidfile) )
	{
		log_warn("Program alread running");
		return 0;
	}

	if ( daemon_flag )		
	{
		daemon(1, 1);
		log_info("Program running as daemon [PID: %d]\n", getpid());
	}

	if (record_daemon_pid(pidfile) < 0)
	{  
		log_error("Record PID to \"%s\" failure\n", pidfile);
		return 0;                                  
	}

	return 1;
}


int proc_check_daemon(char *pidfile)
{
	pid_t				pid = -1;
	struct stat			fstatbuf;

	if ( !stat(pidfile, &fstatbuf) )
	{
		log_info("PID record file \"%s\" exist", pidfile);

		pid = get_daemon_pid(pidfile);
		if ( pid > 0 )
		{
			if ( !kill(pid, 0) )	
			{
				log_error("Program with PID[%d] is running\n", pid);
				return 0;
			}

			remove(pidfile);
			return 1;
		}
		if ( 0 == pid )
		{
			log_debug("Read program PID failure\n");	
			remove(pidfile);
			return 1;
		}

		log_error("Read record file failure", pidfile);
		return 0;
	}

	return 1;
}


pid_t get_daemon_pid(char *pidfile)
{
	pid_t			pid;
	FILE			*f;
	char			pid_ascii[PID_SIZE];

	f = fopen(pidfile, "rb");
	if ( f != NULL )
	{
		(void)fgets(pid_ascii, PID_SIZE, f);
		(void)fclose(f);
		pid = atoi(pid_ascii);
	}
	else
	{
		log_error("open PID record file failure\n");
		return -1;
	}
	return pid;
}


int record_daemon_pid(char *pidfile)
{
	struct stat 		fstatbuf;
	int					fd = -1;
	int 				mode = S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH;
	char				ipc_dir[64] = {0};
	char				pid[PID_SIZE];

	strncpy(ipc_dir, pidfile, 64);

	dirname(ipc_dir);

	if ( stat(ipc_dir, &fstatbuf) < 0 )
	{
		if ( mkdir(ipc_dir, mode) < 0 )
		{
			log_error("create \"%s\" failure\n", ipc_dir);
			return -1;
		}

		(void)chmod(ipc_dir, mode);
	}

	mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH;
	fd = open(pidfile, O_RDWR|O_CREAT|O_TRUNC, mode);
	if ( fd < 0 )
	{
		log_error("create \"%s\" failure\n", pidfile);
		return -1;
	}

	snprintf(pid, sizeof(pid), "%u\n", (unsigned)getpid());
	write(fd, pid, strlen(pid));
	close(fd);

	return 0;
}


int stop_background_running(char *pidfile)
{
	pid_t            pid = -1;
	struct stat      fstatbuf;

	if ( stat(pidfile, &fstatbuf) < 0)
	{
		return 0;
	}

	pid = get_daemon_pid(pidfile);
	if (pid > 0)
	{
		while ( (kill(pid, 0) ) == 0 )
		{
			kill(pid, SIGTERM);
			sleep(1);
		}

		remove(pidfile);
	}

	return 0;
}

